package com.yixin.aop;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yixin.entity.OperateLog;
import com.yixin.mapper.OperateLogMapper;
import com.yixin.utils.CurrentHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

@Slf4j
@Aspect
@Component
public class OperateLogAspect {

    @Autowired
    private OperateLogMapper operateLogMapper;

    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 定义切点：拦截 com.yixin.controller 包下所有 public 方法
     * 可以进一步限定带有 @AutoLog 注解的方法
     */
    @Around("@annotation(com.yixin.anno.Log)")
    public Object recordOperateLog(ProceedingJoinPoint joinPoint) throws Throwable {
        // 1. 获取目标类和方法信息
        Class<?> targetClass = joinPoint.getTarget().getClass();
        String className = targetClass.getName();
        String methodName = joinPoint.getSignature().getName();

        // 2. 获取请求中的操作人ID（假设从 session 或 token 中获取）
        Integer operateEmpId = getOperateEmpId();

        // 3. 获取方法参数并转为 JSON 字符串
        Object[] methodArgs = joinPoint.getArgs();
        String methodParams = toJson(methodArgs);

        // 4. 记录开始时间
        long startTime = System.currentTimeMillis();
        LocalDateTime operateTime = LocalDateTime.now();

        // 5. 执行目标方法
        Object result = null;
        long costTime = 0L;
        String returnValue = "";
        try {
            result = joinPoint.proceed();
            costTime = System.currentTimeMillis() - startTime;
            returnValue = toJson(result);
        } catch (Throwable e) {
            costTime = System.currentTimeMillis() - startTime;
            returnValue = "{\"error\": \"" + e.getMessage() + "\"}";
            throw e; // 继续抛出异常
        } finally {
            // 6. 构建日志对象并保存
            OperateLog operateLog = new OperateLog();
            operateLog.setOperateEmpId(operateEmpId);
            operateLog.setOperateTime(operateTime);
            operateLog.setClassName(className);
            operateLog.setMethodName(methodName);
            operateLog.setMethodParams(methodParams);
            operateLog.setReturnValue(returnValue);
            operateLog.setCostTime(costTime);

            log.info("操作日志：{}", operateLog);
            // 7. 保存到数据库
            operateLogMapper.insert(operateLog);
        }

        return result;
    }

    /**
     * 获取操作人ID（根据实际业务调整）
     * 示例：从 Session 或 JWT Token 中获取
     */
    private Integer getOperateEmpId() {
        return CurrentHolder.getCurrentId();
    }

    /**
     * 将对象转为 JSON 字符串
     */
    private String toJson(Object object) {
        if (object == null) return "null";
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            return object.toString();
        }
    }
}